////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016-2017 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file camxthreadqueue.h
/// @brief Provides queue utilities for runtime jobs in thread pool
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef CAMXTHREADQUEUE_H
#define CAMXTHREADQUEUE_H

#include "camxtypes.h"
#include "camxosutils.h"
#include "camxthreadcommon.h"
#include "camxthreadjoblist.h"

CAMX_NAMESPACE_BEGIN

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Job Queue
///
///        A job queue that contains pointers to runtime jobs of a specific logical priority
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class JobQueue
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// JobQueue
    ///
    /// @brief  Constructor for JobQueue object
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    JobQueue();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ~JobQueue
    ///
    /// @brief  Destructor for JobQueue object
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ~JobQueue();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Enqueue
    ///
    /// @brief  Enqueue a runtime job
    ///
    /// @param  pJob         Pointer to the runtime job
    /// @param  pJobRegistry Pointer to job registry
    ///
    /// @return Success or EFailed
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult Enqueue(
        RuntimeJob*  pJob,
        JobRegistry* pJobRegistry);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// UnlockQueue
    ///
    /// @brief  Unlock queue
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID UnlockQueue();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// LockQueue
    ///
    /// @brief  Lock queue
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID LockQueue();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// HasJobs
    ///
    /// @brief  Returns if queue has jobs
    ///
    /// @return BOOL
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL HasJobs();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CheckAndDequeue
    ///
    /// @brief  Conditionally dequeue a runtime job, based on the overall state of jobs
    ///
    /// @param  ppJob        Pointer to address of a runtime job
    /// @param  pJobRegistry Pointer to job registry
    ///
    /// @return One of JobStatus
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    JobStatus CheckAndDequeue(
        RuntimeJob**    ppJob,
        JobRegistry*    pJobRegistry);

private:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetFirstEligibleJob
    ///
    /// @brief  Get the first eligible job of the family which can be moved to Ready state
    ///
    /// @param  pJobRegistry Pointer to job registry
    /// @param  hJob         Handle to the current job, of which the first eligible job in the family will be returned
    ///
    /// @return One of JobStatus
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    RuntimeJob* GetFirstEligibleJob(
        JobRegistry* pJobRegistry,
        UINT64       hJob);

    // Disable copy constructor and assignment operator
    JobQueue(const JobQueue&) = delete;
    JobQueue& operator=(const JobQueue&) = delete;

    UINT32      m_head;                     ///< Queue head
    UINT32      m_tail;                     ///< Queue tail
    RuntimeJob* m_pJobs[MaxRuntimeJobs];    ///< Pointer to the runtime jobs

    Mutex*      m_pQueueLock;               ///< Queue lock
};

CAMX_NAMESPACE_END

#endif // CAMXTHREADQUEUE_H
